home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC Graphics Unleashed
/
PC Graphics Unleashed.iso
/
ch12
/
blobdraw.poc
< prev
next >
Wrap
Text File
|
1994-07-31
|
12KB
|
432 lines
/////////////////////////////////////////////////////////////
// BLOBDRAW.POC V 1.1 //
// Animated Blob Generator for Autodesk Animator Pro. //
// (c) 1994 James P. Hawkins //
// 18 Marlpit Pl. //
// Middletown, NJ 07748 //
// //
// See "3D Artist", issue #14 PP. 41-42 //
// "Introduction to Blobs" by Alfonso Hermida //
// //
/////////////////////////////////////////////////////////////
#pragma poco library "pdracces.poe" // extended picture I/O library
#pragma poco stacksize 32k
#include <errcodes.h>
#define MAXBLOBS 100
int color,
numcol, // Screen width in pixels
numrow, // Screen height in pixels
curframe, // Current frame
skip = 1.0, // Set skip > 1.0 for faster spaced out pixel plot
num_frames, // Total number of frames
color_mode = 1, // Color exponential gradient if default
old_color_idx; // To save previous color
// Blob space is 8 X 6 with 0 at center
double xmin = -4.0,
ymin = -3.0,
xmax = 4.0,
ymax = 3.0,
threshold = 0.5;
FILE *fp;
///////////////////////////////////////////////////////////////////
// BLOB DATUM
// x, y is the center in BLOB space (-4 < x < 4, -3 < y < 3)
// dx, dy are the amount x and y are incremented or decremented
// for motion to the next frame, they will be 0 if the blob is
// stationary.
// radius is the blob radius in BLOB space units
// and strength is the max strength at the blob center.
///////////////////////////////////////////////////////////////////
typedef struct {
double x,y; // Center of blob
double dx, dy; // animation motion deltas
double radius, strength;
} BLOB;
BLOB blobs[MAXBLOBS];
int bnum; // Blob number
// Function prototypes
void blobdemo(void);
void blobinc(void);
int blobinfo(void);
void GrayPaletteInit(void);
////////////////////////////////////////////////////
// MENUS
char main_header[] = "Main menu";
int main_choice;
char *main_choices[] = {
"CREATE BLOB SCENE",
"DEMO",
};
enum {
MAIN_DEMO,
MAIN_BLOB_INFO,
};
//////////////////////////////////////////////////
// MAIN //
//////////////////////////////////////////////////
main()
{
double r, t, x, y, temp;
int i, j, k;
int max_strength; // The highest strength possible (for color calc)
GetPhysicalSize(&numcol, &numrow); // Get the screen res from anipro
num_frames = GetFrameCount(); // Get number of frames available
old_color_idx = GetColor(); // Save old color index
// Display the main menu and act on the choice
main_choice = Qmenu(main_choices, 2, main_header);
switch (main_choice)
{
case MAIN_DEMO:
blobdemo();
break;
case MAIN_BLOB_INFO:
if(!blobinfo())
return;
}
for(curframe = 1; curframe <= num_frames; curframe++)
{
Clear(); // clear screen
printf("Generating frame %d of %d.", curframe, num_frames);
for(j = 0;j <= numrow; j += skip) {
y = j * (ymax - ymin) / numrow + ymin;
for(i = 0; i <= numcol; i += skip) {
x = i * (xmax - xmin) / numcol + xmin;
t = 0.0;
// Add the combined strengths of the blobs at this point
for(k = 0; k < bnum; k++) {
// Calculate distance from blob center
r = sqrt((x - blobs[k].x) * (x - blobs[k].x) +
(y - blobs[k].y) * (y - blobs[k].y));
//
// If distance is within blob radius calculate 't'
// from: t = strength(1 - (r/radius)^2)^2
//
if( r <= blobs[k].radius ) {
temp = r / blobs[k].radius;
temp *= temp;
temp = 1.0 - temp;
temp *= temp;
t += blobs[k].strength * temp;
}
}
//
// If the combined strength at this coordinate exceeds
// the threshold, plot a point.
// If color mode is on, the color is a function of
// the strength, based on 256 color palette.
//
if (t >= threshold) {
switch(color_mode) {
case 0:
color = GetColor();
break;
case 1:
color = 255 * (1 - exp(-t));
if(t == threshold) color /= 4;
break;
case 2:
color = 255 * exp(-t);
break;
case 3:
color = t * 255;
if(color > 255)
color = 255;
break;
case 4:
// Calculate maximum possible strength for use
// in computing color index
for(k = 0, max_strength = 0.0; k < bnum; k++)
max_strength += blobs[k].strength;
color = ((int)((t/max_strength) * 255) % 255);
break;
case 5:
color = t * 255;
break;
}
SetColor(color);
Dot(i, j);
}
}
}
NextFrame();
blobinc();
}
SetColor(old_color_idx);
unprintf();
}
////////////////////////////////////////////////////////////
// MOVE ALL BLOBS FOR NEXT FRAME
//
void blobinc(void)
{
int k;
for(k = 0; k < bnum; k++)
{
blobs[k].x += blobs[k].dx;
blobs[k].y += blobs[k].dy;
}
}
//////////////////////////////
// BLOB MENU DEFINITIONS //
//////////////////////////////
//
int blob_choice = -1;
char blob_header[] = "BLOB DATA ENTRY";
char *blob_choices[] = {
"Add A Blob",
"Set Threshold Index (default = 5)",
"Set Color Mode",
"Set Palette to Grayscale",
"GO!",
};
enum {
BLOB_GO,
BLOB_ADD_BLOB,
BLOB_SET_THRESH,
BLOB_SET_COLOR_MODE,
BLOB_GRAY,
};
double tenths[21] = {-1.0, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2,
-0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0};
////////////////////////////////////////////////////////////////////////
// ENTER YOUR OWN BLOB ANIMATION DATA
//
int blobinfo(void)
{
int i1, j1, i2, j2, radius, threshindex = 5, strengthindex = 10;
double x1, x2, y1, y2;
int go_flag = 0;
int old_red, old_green, old_blue;
int old_filled;
#ifdef DEBUG
fp = fopen("pdump.txt", "w");
#endif
// Temporarily put WHITE in index 1 and use it for
// the blob placement and path, restore the old color in
// index 1 when done.
SetColor(1);
GetColorMap(1, &old_red, &old_green, &old_blue);
SetColorMap(1, 255, 255, 255);
//
// Temporarily set to NON-FILLED mode to make the
// BLOB outlines and paths easier to see.
//
old_filled = GetFilled();
SetFilled(0);
bnum = 0;
while (blob_choice != BLOB_GO)
{
blob_choice = Qmenu(blob_choices, 5, blob_header);
switch (blob_choice)
{
case BLOB_GO:
go_flag++;
break;
case BLOB_SET_THRESH:
Qnumber(&threshindex, 0, 10, "SET THRESHOLD INDEX");
threshold = tenths[threshindex + 10];
break;
case BLOB_SET_COLOR_MODE:
Qnumber(&color_mode, 0, 5, "SET COLOR MODE");
break;
case BLOB_GRAY:
GrayPaletteInit();
GetColorMap(1, &old_red, &old_green, &old_blue);
SetColorMap(1, 255, 255, 255);
break;
case BLOB_ADD_BLOB:
if(RubCircle(&i1, &j1, &radius)) // Get center and radius
Circle(i1, j1, radius); // Draw a circle
else
return(0);
if(!RubLine(i1, j1, &i2, &j2)) { // Get motion path
i2 = i1;
j2 = j1;
}
Line(i1, j1, i2, j2); // Draw the path
y1 = (double)j1 * (ymax - ymin) / numrow + ymin;
y2 = (double)j2 * (ymax - ymin) / numrow + ymin;
x1 = (double)i1 * (xmax - xmin) / numcol + xmin;
x2 = (double)i2 * (xmax - xmin) / numcol + xmin;
strengthindex = 10;
Qnumber(&strengthindex, -10, 10, "SET BLOB STRENGTH INDEX");
strengthindex += 10;
blobs[bnum].x = x1;
blobs[bnum].y = y1;
blobs[bnum].radius = (double)radius * (ymax - ymin) / numrow;
blobs[bnum].strength = tenths[strengthindex];
blobs[bnum].dx = (x2 - x1) / num_frames;
blobs[bnum].dy = (y2 - y1) / num_frames;
bnum++;
#ifdef DEBUG
fprintf(fp,"\nblobs[%d].x = %f\n", bnum, blobs[bnum].x);
fprintf(fp,"blobs[%d].y = %f\n", bnum, blobs[bnum].y);
fprintf(fp,"blobs[%d].radius = %f\n", bnum, blobs[bnum].radius);
fprintf(fp,"blobs[%d].strength = %f\n", bnum, blobs[bnum].strength);
fprintf(fp,"blobs[%d].dx = %f\n", bnum, blobs[bnum].dx);
fprintf(fp,"blobs[%d].dy = %f\n\n", bnum, blobs[bnum].dy);
#endif
break;
}
if(go_flag){
break;
}
}
#ifdef debug
fprintf(fp,"\nbnum = %d\n", bnum);
fclose(fp);
#endif
// Restore old color in index 1 and old filled mode.
SetFilled(old_filled);
SetColorMap(1, old_red, old_green, old_blue);
if(!color_mode)
SetColor(old_color_idx);
return(1);
}
/////////////////////////////////////////////////////////////
// DEMONSTRATION
//
void blobdemo(void)
{
//
// DEMO BLOBS
//
// define blob #1
blobs[0].x = -3.0;
blobs[0].y = 0;
blobs[0].radius = 1.0;
blobs[0].strength = 1.0;
blobs[0].dx = 0.25;
blobs[0].dy = 0.0;
// define blob #2
blobs[1].x = -1.375;
blobs[1].y = 0.64952;
blobs[1].radius = 1.0;
blobs[1].strength = 1.0;
blobs[1].dx = 0.0;
blobs[1].dy = 0.0;
// define blob #3
blobs[2].x = -1.375;
blobs[2].y = -0.64952;
blobs[2].radius = 1.0;
blobs[2].strength = 1.0;
blobs[2].dx = 0.0;
blobs[2].dy = 0.0;
// define blob #4
blobs[3].x = 0.625;
blobs[3].y = 0.64952;
blobs[3].radius = 1.0;
blobs[3].strength = 1.0;
blobs[3].dx = 0.0;
blobs[3].dy = 0.0;
// define blob #5
blobs[4].x = 0.625;
blobs[4].y = -0.64952;
blobs[4].radius = 1.0;
blobs[4].strength = 1.0;
blobs[4].dx = 0.0;
blobs[4].dy = 0.0;
// define blob #6
blobs[5].x = 2.625;
blobs[5].y = 0.64952;
blobs[5].radius = 1.0;
blobs[5].strength = 1.0;
blobs[5].dx = 0.0;
blobs[5].dy = 0.0;
// define blob #7
blobs[6].x = 2.625;
blobs[6].y = -0.64952;
blobs[6].radius = 1.0;
blobs[6].strength = 1.0;
blobs[6].dx = 0.0;
blobs[6].dy = 0.0;
bnum = 7;
color_mode = 4;
}
//////////////////////////////////////////////////////////////////////////
//
//
void GrayPaletteInit(void)
{
int index;
int Palette_Map[256][3];
for (index = 0; index < 256; index++)
{
// Gray Gradient
Palette_Map[index][0] = index;
Palette_Map[index][1] = index;
Palette_Map[index][2] = index;
}
// Set the palette for all frames, then reset to the first frame
SetFrame(0);
for(curframe = 1; curframe <= num_frames; curframe++) {
SetScreenColorMap(GetPicScreen(), &Palette_Map[0][0]);
NextFrame();
}
SetFrame(0);
}